package bluetooth;


import javax.microedition.lcdui.*;
import java.io.*;
import java.io.DataInputStream;
import java.io.DataOutputStream;

import java.io.IOException;

import java.util.Vector;

import javax.bluetooth.DiscoveryAgent;
import javax.bluetooth.LocalDevice;
import javax.bluetooth.ServiceRecord;
import javax.bluetooth.UUID;
import javax.microedition.io.Connector;
import javax.microedition.io.StreamConnection;
import javax.microedition.io.StreamConnectionNotifier;

public class Server implements Runnable
{
    private Connection connection;
    private LocalDevice local = null;
    private ClientProcessor processor;
    private DataOutputStream dos;
    private boolean isClosed = false;
    private StreamConnectionNotifier notifier;
    boolean isAttack_1, isObject_1,isEscape_1;
	boolean isSkill_1;
	int skill_1;
	boolean isAttack_2, isObject_2,isEscape_2;
	boolean isSkill_2;
	int skill_2;

    private String connectionURL =
        "btspp://localhost:F0E0D0C0B0A000908070605040302010;" +
        "authenticate=false;encrypt=false;name=FIR Server";
    
    private Thread accepterThread;   
    public Server(Connection connection)
    {
        this.connection = connection;
    }

    public void start()
    {
        accepterThread = new Thread(this);
        accepterThread.start();
    }

    public void run()
    {
        boolean isBTReady = false;
        try
        {
            local = LocalDevice.getLocalDevice();
            local.setDiscoverable(DiscoveryAgent.GIAC);
        }
        catch (Exception e)
        {
            System.out.println("Can't set discoverable mode...");
        }

        try
        {
            notifier = (StreamConnectionNotifier)Connector.open(connectionURL);
            isBTReady = true;
        }
        catch (Exception e)
        {
            System.err.println("Can't initialize bluetooth: " + e);
        }     
        connection.completeInitialization(isBTReady);
        if (!isBTReady)
        {
            return ;
        }
        processor = new ClientProcessor();   
        while (!isClosed)
        {
            StreamConnection conn = null;

            try
            {
                conn = notifier.acceptAndOpen();
            }
            catch (IOException e)
            {             
                continue;
            }
            processor.addConnection(conn);
        }
    } 


    public void sendMessage(boolean isAttack, boolean isObject,boolean isSkill, int skill, boolean isEscape)
    {
    	isAttack_1 = isAttack; 
		isObject_1 = isObject;
		isSkill_1 = isSkill;
		skill_1 = skill;
		isEscape_1 = isEscape;
        try
        {
        	
        	dos.writeBoolean(isAttack_1);
            dos.writeBoolean(isObject_1);
            dos.writeBoolean(isSkill_1);
            dos.write(skill_1);
            dos.writeBoolean(isEscape_1);
            dos.flush();
            dos.close();
        }
        catch (IOException e){System.out.println("server send");}
    }

    private void processConnection(StreamConnection conn)
    {
        try
        {
            dos = conn.openDataOutputStream();
        }
        catch (Exception e){}
        readInputString(conn);
    }

    private void readInputString(StreamConnection conn)
    {
    	boolean isAttack1, isObject1,isEscape1;
    	boolean isSkill1;
    	int skill1;
        try
        {
            DataInputStream dis = conn.openDataInputStream();
            isAttack1 = dis.readBoolean();
            isObject1 = dis.readBoolean();
            isSkill1 = dis.readBoolean();
            skill1 = dis.read();
            isEscape1 = dis.readBoolean();
            dis.close();
            
            connection.receiveMessage(isAttack1, isObject1,isSkill1,skill1,isEscape1);
        }
        catch (Exception e)
        {
            e.printStackTrace();
            System.out.println("Exception...");
        }
    }

    private class ClientProcessor implements Runnable
    {
        private Thread processorThread;
        private Vector queue = new Vector();
        ClientProcessor()
        {
            processorThread = new Thread(this);
            processorThread.start();
        }
        public void run()
        {
            while (!isClosed)
            {

                synchronized(this)
                {
                    if (queue.size() == 0)
                    {
                        try
                        {
                            wait();
                        }
                        catch (InterruptedException e)
                        {
                            System.err.println("Unexpected exception: " + e);
                            destroy(false);
                            return ;
                        }
                    }
                }
                StreamConnection conn;
                synchronized(this)
                {
                    if (isClosed)
                    {
                        return ;
                    }
                    conn = (StreamConnection)queue.firstElement();
                    queue.removeElementAt(0);
                    processConnection(conn);
                    try
                    {
                        dos = conn.openDataOutputStream();
                    }
                    catch (Exception e){}            
                }
            }
        }

     
        void addConnection(StreamConnection conn)
        {
            synchronized(this)
            {
                queue.addElement(conn);
                notify();
            }
        }


        void destroy(boolean needJoin)
        {
            StreamConnection conn;
            synchronized(this)
            {
                notify();

                while (queue.size() != 0)
                {
                    conn = (StreamConnection)queue.firstElement();
                    queue.removeElementAt(0);

                    try
                    {
                        conn.close();
                    }
                    catch (IOException e){}
                  
                }
            }
   
            try
            {
                processorThread.join();
            }
            catch (InterruptedException e){}         
        }
    } 
}








